package com.leyou.user.service;

import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.utils.RegexUtils;
import com.leyou.user.dto.UserDTO;
import com.leyou.user.entity.User;
import com.leyou.user.mapper.UserMapper;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.leyou.common.constants.MQConstants.Exchange.SMS_EXCHANGE_NAME;
import static com.leyou.common.constants.MQConstants.RoutingKey.SMS_CODE_KEY;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;
    /**
     * - true：可用  表中没有此数据
     * - false：不可用  表中已存在此数据
     * @param data
     * @param type  1，用户名；2，手机号码
     * @return
     */
    public Boolean checkData(String data, Integer type) {
        User u = new User();//接收查询条件
        if(type==1){  //用户名
            u.setUsername(data);
        }else if(type==2){
            u.setPhone(data);
        }else {
            throw new LyException(ExceptionEnum.INVALID_PARAM_ERROR);
        }
        int count = userMapper.selectCount(u); //只查出数量即可
        return count==0;
    }


    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private AmqpTemplate amqpTemplate;
    public void sendCode(String phone) {
//        - 验证手机号格式 正则表达式
        if(!RegexUtils.isPhone(phone)){
            throw new LyException(ExceptionEnum.INVALID_PHONE_NUMBER);
        }
//        - 生成验证码
        String randomCode = RandomStringUtils.randomNumeric(4);
//        - 保存验证码到redis
        redisTemplate.boundValueOps("sms_code"+phone).set(randomCode,30, TimeUnit.SECONDS);  //为了测试设置了30秒
//        - 发送RabbitMQ消息到ly-sms
        Map<String ,String> map = new HashMap<>();
        map.put("phone",phone);//"13613304022"
        map.put("signName","快乐优雅购物");
        map.put("templateCode","SMS_173479212");
        map.put("templateParam","{\"code\":\""+randomCode+"\"}");
        amqpTemplate.convertAndSend(SMS_EXCHANGE_NAME,SMS_CODE_KEY,map);

    }


    @Autowired
    private BCryptPasswordEncoder passwordEncoder ;


    public void register(User user, String code) {
//        user.getPassword() 不能少于4位  不能为空
//        user.getUsername() 不能少于4位  不能为空

//        - 验证短信验证码  页面上输入的 code  redis中获取
        String redisCode = redisTemplate.boundValueOps("sms_code" + user.getPhone()).get();
        if(redisCode==null){
            throw new LyException(ExceptionEnum.INVALID_VERIFY_CODE);
        }
        if(!code.equals(redisCode)){
            throw new LyException(ExceptionEnum.INVALID_VERIFY_CODE);
        }
//        Md5Hash(原密码，自己的盐，加几次)
//        spring的加密算法  很变态 加随机盐
//        - 对密码加密
        String password = passwordEncoder.encode("123456"); //加密
//        passwordEncoder.matches("123456","2atrelsufytcrfytdrstbdfngifo");
//        - 写入数据库
        user.setPassword(password);
        userMapper.insertSelective(user);
    }

    /**
     * @param username
     * @param password
     * @return
     */
    public UserDTO queryByUsernameAndPassword(String username, String password) {  //password:123456
//        select * from tb_user where username=lisi and password=123456
//        select * from tb_user where username=?
//        先通过用户名查询用户然后在比较密码

//        spring的BCrypt算法加密：加密的逻辑是会使用随机盐（我们不知道，但是spring框架知道）
        User u  = new User();
        u.setUsername(username);
        User user = userMapper.selectOne(u);

        if(user==null){
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }

        String passwordDb = user.getPassword(); // $2a$10$5EWTZySAYAAw5Ox6.QhSY.VHhV6GG/0aSEhhNViZt1p5Ixr8sv116
//        123456----Md5->sfoqiw6efturhuff-->123456
        boolean matches = passwordEncoder.matches(password, passwordDb); //比较密码
        if(!matches){
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }
        return BeanHelper.copyProperties(user,UserDTO.class);

    }
}
